package currency

abstract class CurrencyZone {
    // 类型上限 Currency为AbstractCurrency子类
    type Currency <: AbstractCurrency

    // 工厂方法
    def make(x: Long): Currency

    // 标准单位
    val CurrencyUnit: Currency

    abstract class AbstractCurrency {
        val amount: Long

        def designation: String

        override def toString: String =
            ((amount.toDouble / CurrencyUnit.amount.toDouble) formatted ("%." + decimals(CurrencyUnit.amount) + "f")
                    + " " + designation)

        private def decimals(n: Long): Int =
            if (n == 1) 0 else 1 + decimals(n / 10)

        def +(that: Currency): Currency =
            make(this.amount + that.amount)

        def *(x: Double): Currency =
            make((this.amount * x).toLong)

        // CurrencyZone#AbstractCurrency 表示入参的必须是某种任意而未知的CurrencyZone的AbstractCurrency类型
        def from(other: CurrencyZone#AbstractCurrency): Currency =
            make(math.round(other.amount.toDouble * Converter.exchangeRate(other.designation)(this.designation)))
    }

}
